package com.tanhua.app.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tanhua.api.service.*;
import com.tanhua.app.Interceptor.UserHolder;
import com.tanhua.app.exception.BusinessException;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.pojo.Question;
import com.tanhua.model.pojo.UserInfo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TanhuaService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private UserApi userApi;

    @DubboReference
    private QuestionApi questionApi;

    @DubboReference
    private UserLikeApi userLikeApi;

    @DubboReference
    private UserLocationApi userLocationApi;

    @Autowired
    private MessagesService messagesService;

    @DubboReference
    private VisitorsApi visitorsApi;


    /**
     * 获取今日佳人
     * @return
     */
    public TodayBest todayBest() {

        // 获取当前用户id
        Long toUserId = UserHolder.getUserId();

        // 获取今日佳人数据
        RecommendUser recommendUser = recommendUserApi.findWithMaxScore(toUserId);

        // 根据今日佳人数据，查询佳人的用户的详细数据
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());

        // 封装数据
        return TodayBest.init(userInfo, recommendUser);
    }


    /**
     * 查询推荐朋友
     * @param dto
     * @return
     */
    public PageResult<TodayBest> recommendation(RecommendUserDto dto) {

        // 获取当前的用户Id
        Long toUserId = UserHolder.getUserId();

        // 根据当前用户id查询推荐用户
        List<RecommendUser> recommendUserList = recommendUserApi.findByUserIdList(toUserId);

        // 判断是否有数据
        if (recommendUserList == null || recommendUserList.isEmpty()) {
            return new PageResult<>(dto.getPage(),dto.getPagesize(), 0L, null);
        }

        // 提取所有的推荐的用户id列表
        List<Long> userIds = CollUtil.getFieldValues(recommendUserList, "userId", Long.class);

        // 进行分页查询
        Page<UserInfo> pages =  userInfoApi.findPageByUesrId(userIds, dto);

        //构建vo
        Map<Long, RecommendUser> recommendUserMap = recommendUserList.stream()
                .collect(Collectors.toMap(RecommendUser::getUserId, Function.identity()));

        List<TodayBest> list = new ArrayList<>();

        for (UserInfo userInfo : pages.getRecords()) {
            RecommendUser recommendUser = recommendUserMap.get(userInfo.getId());
            TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
            list.add(todayBest);
        }

        return new PageResult<>(pages.getCurrent(), pages.getSize(), pages.getTotal(), list);

    }


    /**
     * 根据用户,查询佳人信息
     * @param userId
     * @return
     */
    public TodayBest findRecommendByUserId(Long userId) {

        // 查询佳人的详情数据
        UserInfo userInfo = userInfoApi.findById(userId);

        // 佳人id和当前用户id查询推荐数据
        RecommendUser recommendUser = recommendUserApi.findByUserIdAndToUserId(userId, UserHolder.getUserId());

        // 保存访客数据
        Visitors visitors = new Visitors();
        visitors.setUserId(userId);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setScore(recommendUser.getScore());
        visitors.setVisitDate(DateUtil.format(new Date(), "yyyyMMdd"));

        visitorsApi.saveVisitors(visitors);


        return TodayBest.init(userInfo, recommendUser);

    }

    /**
     * 根据用户id,查询陌生人信息
     * @param userId
     * @return
     */
    public String findQuestion(Long userId) {

        Question question = questionApi.findByUserID(userId);

        return question == null ? "我是谁？" : question.getTxt();
    }

    /**
     * 回复陌生人消息
     * @param userId
     * @param reply
     */
    public void sendQuestions(Long userId, String reply) {

        String hxUser = userApi.findByUserId(userId).getHxUser();

        // 根据用户id,查询用户详情数据
        UserInfo userInfo = userInfoApi.findById(UserHolder.getUserId());

        // 获取陌生人问题
        String strangerQuestion = this.findQuestion(userId);

        // 封装数据
        Map<String, Object> map = new HashMap<>();
        map.put("userId", UserHolder.getUserId());
        map.put("huanXinId", Constants.HX_USER_PREFIX + UserHolder.getUserId());
        map.put("nickname", userInfo.getNickname());
        map.put("strangerQuestion", strangerQuestion);
        map.put("reply", reply);

        // 将Map转换成json数据
        String message = JSON.toJSONString(map);

        Boolean aBoolean = huanXinTemplate.sendMsg(hxUser, message);

        if (!aBoolean) {
            throw new BusinessException(ErrorResult.HuanXinSendError());
        }
    }

    @Value("${tanhua.default.recommend.users}")
    private String defaultIds;

    // 查询探花列表
    public List<TodayBest> findCards() {
        // 根据当前用户，查询喜欢/不喜欢的用户列表
        List<Long> likeUserIds =  userLikeApi.findByUserId(UserHolder.getUserId());

        // 根据用户列表查询用户列表的推荐人信息，并排除掉喜欢和不喜欢的数据
        List<RecommendUser> userList = recommendUserApi.findByUserIds(UserHolder.getUserId(), likeUserIds, 10);

        // 判断用户是否有推荐人
        if (CollUtil.isEmpty(userList)) {
            // 没有推荐人，获取默认数据
            String[] arr = defaultIds.split(",");
            userList = new ArrayList<>();
            for (String userId : arr) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setToUserId(UserHolder.getUserId());
                recommendUser.setUserId(Long.parseLong(userId));
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUser.setDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));

                userList.add(recommendUser);
            }
        }

        // 抽取用户推荐人的Id值
        List<Long> ids = userList.stream().map(RecommendUser::getUserId).collect(Collectors.toList());

        // 根据用户Ids查询用户的详情数据,并封装成map
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids)
                .stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));

        // 封装结果数据
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser recommendUser : userList) {
            TodayBest tb = TodayBest.init(map.get(recommendUser.getUserId()),recommendUser);

            list.add(tb);
        }

        return list;

    }

    // 添加探花喜欢
    public void saveUserLikeByLove(Long likeUserId) {
        // 获取当前用户id
        Long userId = UserHolder.getUserId();

        // 添加喜欢探花数据
        Boolean flag = userLikeApi.saveUserLikeByLove(userId, likeUserId, true);

        // 判断是否添加成功
        if (!flag) {
            throw new BusinessException(ErrorResult.UserLikeAddError());
        }

        // 将数据添加到redis中，先删除对应的喜欢数据
        String key = Constants.USER_LIKE_KEY + userId;
        redisTemplate.opsForSet().remove(key, likeUserId.toString());
        redisTemplate.opsForSet().add(key, likeUserId.toString());

        // 判断是否是双向喜欢
        Boolean member = redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + likeUserId,
                userId.toString());
        if (member) {
            // 成立表示双向喜欢，相互添加好友
            messagesService.saveFriend(likeUserId);
        }
    }


    // 探花不喜欢
    public void saveUserLikeByUnLove(Long likeUserId) {

        Long userId = UserHolder.getUserId();

        // 添加探花不喜欢
        boolean flag = userLikeApi.saveUserLikeByLove(userId, likeUserId, false);

        if (!flag) {
            throw new BusinessException(ErrorResult.UserLikeAddError());
        }

        // 将数据添加到redis中
        String key = Constants.USER_NOT_LIKE_KEY + userId;
        redisTemplate.opsForSet().remove(key, likeUserId.toString());
        redisTemplate.opsForSet().add(key, likeUserId.toString());

        // 判断双方是不是都不喜欢
        Boolean member = redisTemplate.opsForSet().isMember(Constants.USER_NOT_LIKE_KEY + likeUserId, userId.toString());
        if (member) {

            // 删除好友数据
            messagesService.deleteFriend(likeUserId);

        }

    }

    // 搜附近的人
    public List<NearUserVo> search(String gender, String distance) {

        // 查需一定距离下附近所有的用户id
        List<Long> ids = userLocationApi.search(UserHolder.getUserId(), Double.valueOf(distance));

        // 判断附近是否有人
        if (CollUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }

        // 根据用户id列表查询对应的用户详情数据
        List<UserInfo> userInfoList = userInfoApi.findByIds(ids);

        // 封装数据
        List<NearUserVo> list = new ArrayList<>();
        for (UserInfo userInfo : userInfoList) {
            if (userInfo.getId() == UserHolder.getUserId()) {
                continue;
            }

            NearUserVo vo = NearUserVo.init(userInfo);
            list.add(vo);
        }

        return list;

    }
}
